import { useState, useEffect } from 'react';
import { message } from 'antd';
import lodash from 'lodash';
import moment from 'moment';

import { CreateTarget } from '../common/CreateTarget';

import { getUserDepID, getUserDepName, padStart } from '@/utils';
import { deletPackService } from '../services/UpdateService';
import { IContractsActionEnum } from '../common/ApplyReducer';
import { LaboratorySelfOrg, addOneAndPad, getExpectSum, onMaximumType, processObjects } from './Format';
import { formatDecimal } from '../../Acommon/PurchaseUilt';

interface useStepPackState {
  // packData: Record<string, any>[];
  setLoading: React.Dispatch<React.SetStateAction<boolean>>;
  setPage: React.Dispatch<React.SetStateAction<number>>;
  setTartetDataSource: React.Dispatch<React.SetStateAction<Record<string, any>[]>>;
  setPackData: React.Dispatch<React.SetStateAction<Record<string, any>[]>>;
  // page: number;
  methods: any;
  dispatch: any;
  state: Record<string, any>;
}

/**
 * @useStepPack 采购申请标包hooks
 * @param packData 标包数据
 * @param page 标包分页数据
 * @param methods 表单实例方法
 * @param setLoading 设置loading
 * @param setPage 设置标包分页数据
 * @param setTartetDataSource 设置标的数据
 * @param setPackData 设置标包数据
 * @returns removeMaterialInfo 确认二次提醒删除方法
 * @returns setRemoveMaterialInfo 设置二次提醒删除数据
 * @returns onRemove 删除事件
 * @returns addPack 添加标包
 * @returns changePage 切换标包分页数据
 * @returns isShowMaterial 选择标的弹窗渲染状态
 * @returns changeTargetInfo 修改标的信息
 * @returns changePage 切换标包分页数据
 * @returns successMaterials 成功分包的标的集合
 * @returns setSuccessMaterials 设置分包的标的集合
 */
export const useStepPack = ({ setLoading, setPage, setTartetDataSource, setPackData, methods, dispatch, state }: useStepPackState) => {
  const { setFieldsValue, resetFields } = methods;

  // 解构
  const { page, packData, successMaterials, setSuccessMaterials, reloadInfoService, applyInfo } = state;

  // 标的列表信息渲染状态
  const [isShowMaterial, setIsShowMaterial] = useState<boolean>(false);

  /**
   * @description 删除二次确认弹窗所需信息
   * @id 物料id
   * @fullName 物料名称
   * @isShow 弹窗渲染状态
   */
  const [removeMaterialInfo, setRemoveMaterialInfo] = useState({
    id: '',
    index: 0,
    type: '',
    name: '',
    content: '',
    isShow: false,
    isBatch: false,
  });

  const { deletePackRun } = deletPackService();

  /** 监听合并了的标的数据 */
  useEffect(() => {
    // 克隆一份数据
    const tempData = lodash.cloneDeep(packData);
    // 当前包的标的
    let nowTempDataML = tempData[page - 1]?.mpurchaseNeedMaterials;
    // 最大supplyType
    const supplyType = onMaximumType(nowTempDataML);
    // 金额
    const resObj = nowTempDataML?.sort((a, b) => b.expectSum - a.expectSum)?.[0];
    // 当数据发生改变，重新计算
    let expectSum = nowTempDataML?.reduce((acc, obj) => acc + Number(obj.expectSum), 0);
    // 给表单设置金额 标的类别： supplyTypeName: resObj?.supplyTypeName,
    setFieldsValue({ expectSum: formatDecimal(expectSum) });
    // 给reducer存储一份类型
    dispatch({ type: IContractsActionEnum?.UpdateSupplyTK, payload: { supplyKind: resObj?.supplyKind, supplyType: resObj?.supplyType } });
    // 更新
    if (tempData?.[page - 1]?.id) {
      tempData[page - 1].expectSum = formatDecimal(expectSum);
      // tempData[page - 1].supplyTypeName = resObj?.supplyTypeName;
      // tempData[page - 1].supplyType = resObj?.supplyType;
      setPackData(tempData);
    }
  }, [successMaterials, page]);

  /**
   * @onRemovePack 删除标包信息
   */
  const onRemovePack = async () => {
    if (packData.length == 1) {
      message.warning('至少保留一个标包！');
      return;
    }

    // 删除包数据集合中该条标的信息
    const tempData = lodash.cloneDeep(packData);
    let id = tempData?.[page - 1]?.id;

    if (id) {
      const { msgFlag, msg } = await deletePackRun({ id: id });
      if (msgFlag) {
        message?.success(msg);
        reloadInfoService();
      }
    } else {
      tempData.splice(page - 1, 1);
      setPackData(tempData);
      if (!tempData.length) {
        setPage(tempData?.length - 1);
      } else {
        // 切换到最新页
        changePage('final', tempData, 0);
      }
    }
  };

  /**
   * @onRemoveTarget 删除标的信息
   * @param id 标的id
   * @param index 当前索引
   */
  const onRemoveTarget = (idList: string, isBatch) => {
    /** 删除包数据集合中该条标的信息 */
    /** 先克隆一份包的数据 */
    const tempData = lodash.cloneDeep(packData);

    /** 找到对应包下的标的数据 */
    let NeedMaterials = tempData[page - 1].mpurchaseNeedMaterials;
    let newNeedMaterials: Record<string, any>[] = [];

    let key = 'id';
    if (isBatch) {
      key = 'materialID';
    }

    NeedMaterials?.forEach((item) => {
      if (idList?.indexOf(item?.[key]) === -1) {
        newNeedMaterials?.push(item);
      }
    });

    tempData[page - 1].mpurchaseNeedMaterials = newNeedMaterials;

    /** 更新 包 数据 */
    setPackData(tempData);

    /** 更新 标的 数据 */
    setTartetDataSource(newNeedMaterials);

    /** 更新 标的 数据 -- 用于计算价值和处理选择物料弹窗的逻辑 */
    setSuccessMaterials(newNeedMaterials);
  };

  /**
   * @onRemove 删除弹窗组件 确认事件
   */
  const onRemove = () => {
    const { id, type, isBatch } = removeMaterialInfo;
    if (type == 'target') {
      onRemoveTarget(id, isBatch);
    } else if (type == 'pack') {
      onRemovePack();
    }
  };

  /**
   * @addPack 添加标包
   */
  const addPack = async () => {
    const tempData = lodash.cloneDeep(packData);
    let packCode = '';
    if (tempData?.length) {
      let info = tempData?.[tempData?.length - 1];
      packCode = `第${addOneAndPad(info?.packCode?.slice(1, 3))}包`;
    } else {
      packCode = `第${padStart(tempData.length + 1, 2)}包`;
    }
    const param = {
      applyDepartmentID: getUserDepID(),
      packCode,
      mpurchaseNeedMaterials: [],
      sourceName: `${getUserDepName()} ${moment().format('YYYYMMDD')}寻源`,
      supplyWay: applyInfo?.supplyWay === 0 || applyInfo?.supplyWay ? applyInfo?.supplyWay : undefined,
      importFlag: 0,
      singleFlag: 0,
      procureOrg: LaboratorySelfOrg(),
    };
    const data = [...tempData, param]; // 将当前包数据推入
    setPackData(data);
    changePage('final', data); // 切换到最新页
  };

  /** 初始化标包 */
  const initAddPack = () => {
    let arr = [
      {
        applyDepartmentID: getUserDepID(),
        packCode: `第01包`,
        mpurchaseNeedMaterials: [],
        sourceName: `${getUserDepName()} ${moment().format('YYYYMMDD')}寻源`,
        supplyWay: applyInfo?.supplyWay === 0 || applyInfo?.supplyWay ? applyInfo?.supplyWay : undefined,
        importFlag: 0,
        singleFlag: 0,
      },
    ];
    setPackData(arr);
    changePage('final', arr); // 切换到最新页
  };

  /**
   * 月度计划使用
   * @changeTargetInfo 添加标的信息
   * @param packInfo 当前新增标的信息
   * @param isShow 当前标的弹窗渲染状态
   * @param Rowfields 标的数据存储字段
   */
  const changeTargetInfo = ({ packInfo, isShow, Rowfields = 'mpurchaseNeedMaterials', flag = true }: Record<string, any>) => {
    /**
     * packData = 分了几个包
     * packInfo【mpurchaseNeedMaterials】= 从选择标的弹窗中选择的数据
     * temp = 克隆的分包数据
     * */
    if (isShow && packInfo?.[Rowfields] && packInfo?.[Rowfields].length) {
      // 克隆一份分包数据
      const temp = lodash.cloneDeep(packData);

      // 初始化方法示例
      const target = new CreateTarget();

      // 获取当前已有标的集合
      const oldTempTargets = temp?.[page - 1]?.[Rowfields]?.map((item: Record<string, any>) => item?.customNeedMatrials)?.flat(Infinity);
      // 将当前已有标的集合规范化，已物料id：materialID为键，需求物料为值进行配对
      // target.addTarget(oldTempTargets, 'materialID');

      // 新增的标的集合
      const tempTargets = packInfo?.[Rowfields] || [];

      // 将新增的标的集合规范化，以物料id：materialID为键，需求物料为值进行配对
      // target.addTarget(tempTargets, 'materialID');

      let cancatArr = [...oldTempTargets, ...tempTargets];
      target.addTarget(cancatArr, 'materialID');

      // 获取合并后的标的 【参数true，将原有标的放入合并数据的某个属性中】
      const getTargets = target.getTarget(true);
      // 将当前合并好的标的数据推入对应包的【mpurchaseNeedMaterials】字段中--包中用来保存标的的字段
      temp[page - 1][Rowfields] = getTargets;

      const { expectSum } = getExpectSum(temp[page - 1][Rowfields]);

      // 同步其他价格
      temp[page - 1]['expectSum'] = temp[page - 1]['needSum'] = temp[page - 1]['planSum'] = temp[page - 1]['factSum'] = expectSum;

      // 设置包的数据
      setPackData(temp);

      // 设置标的数据
      setTartetDataSource(temp[page - 1][Rowfields]);

      // 设置成功合并后的标的
      setSuccessMaterials(processObjects(temp[page - 1][Rowfields]));
    }
    if (flag) {
      setIsShowMaterial(isShow);
    }
  };

  /**
   * 零星采购使用
   * */
  const changePiecemealInfo = ({ packInfo, isShow, Rowfields = 'mpurchaseNeedMaterials', flag = true }: Record<string, any>) => {
    if (isShow && packInfo?.[Rowfields] && packInfo?.[Rowfields].length) {
      // 克隆一份分包数据
      const temp = lodash.cloneDeep(packData);
      temp[page - 1][Rowfields] = packInfo?.[Rowfields];
      const { expectSum } = getExpectSum(temp[page - 1][Rowfields]);
      // 同步其他价格
      temp[page - 1]['expectSum'] = temp[page - 1]['needSum'] = temp[page - 1]['planSum'] = temp[page - 1]['factSum'] = expectSum;
      // 设置包的数据
      setPackData(temp);
      // 设置标的数据
      setTartetDataSource(temp[page - 1][Rowfields]);
      // 设置成功合并后的标的
      setSuccessMaterials(temp[page - 1][Rowfields]);
    }
  };

  /**
   * @changeStep 修改步骤条
   * @param state prev 为上一步、next下一步
   */
  const changePage = async (state: string, data: Record<string, any>[] = [], pageCurrent: number | null = null) => {
    // debugger
    setLoading(true);
    let current = page;
    if (state == 'prev') {
      current = page - 1;
    } else if (state == 'reset') {
      current = 1;
    } else if (state == 'final') {
      if (pageCurrent) {
        current = pageCurrent;
      } else {
        current = data?.length;
      }
    } else {
      current = page + 1;
    }

    setPage(current);

    await resetFields();
    //  防止packData批量更新无法获取最新数据，默认使用data
    const tempData = data?.length ? data : packData;
    if (typeof tempData?.[current - 1]?.expectSum != 'undefined' && tempData?.[current - 1]?.expectSum) {
      tempData[current - 1].expectSum = Number(tempData?.[current - 1]?.expectSum)?.toFixed(2);
    }
    // 更新当前页数包的信息与标的信息
    await methods.setFieldsValue(tempData?.[current - 1]);
    setTartetDataSource(tempData?.[current - 1]?.mpurchaseNeedMaterials);
    setPackData(tempData);

    // // TODO: 梁豪杰 为演示延长loading效果 后续删除
    const timer = setTimeout(() => {
      setLoading(false);
      clearTimeout(timer);
    }, 200);
  };

  return {
    change: {
      addPack,
      initAddPack,
      changePage,
      changeTargetInfo,
      changePiecemealInfo,
    },
    remove: {
      removeMaterialInfo,
      setRemoveMaterialInfo,
      onRemove,
    },
    isShowMaterial,
    successMaterials,
    setSuccessMaterials,
  };
};
